package buildtools;

import java.util.ArrayList;
import java.util.Iterator;

import component.Ball;
import component.ComponentFactory;
import component.Status;
import component.Structure;
import component.Tube;

import math.Spherical;


public class TubeAdder {
		
	private ArrayList<Spherical> takenPositions = new ArrayList<Spherical>();

	private Ball ball = null;
	
	private Structure structure;
	
	private ComponentFactory factory;
	
	private Connector connector;;
	
	public TubeAdder(Structure structure, ComponentFactory factory, Connector connector) {
		this.structure = structure;
		this.factory = factory;
		this.connector = connector;
	}
	
	public void addToBall(Ball ball) {
		this.ball = ball;
		
		if (mapTakenPositions(ball)) createTubeList();
	}
	
	public boolean selectTube(Tube tube) {
		if (!tube.isValidPosition())
			return false;
	
		tube.setStatus(Status.NORMAL);
		structure.transferToPermanent(tube);

		connector.connectToBall(tube);
		
		clearData();
		
		return true;
	}
	
	public void clearData() {
		takenPositions.clear();
		structure.clearTemporaryComponents();
		ball = null;
	}
	
	public boolean isActive() {
		return ball != null ? true : false;
	}
	
	private boolean mapTakenPositions(Ball ball) {
		Tube testTube = factory.createTube(ball.getPos(), new Spherical());

		double y = 0;
	
		boolean hasFreeSlots = false;
		
		for (int i = 0 ; i <= 3 ; i ++) {
			
			testTube.setRotation(0, y);
			
			if (!testTube.isValidPosition()) 
				takenPositions.add(new Spherical(0 , y));
			else
				hasFreeSlots = true;
				
			if (y == 0) {
				testTube.setRotation(Math.PI/2, y);
				if (!testTube.isValidPosition()) 
					takenPositions.add(new Spherical(Math.PI/2 ,y ));
				else
					hasFreeSlots = true;
				
				testTube.setRotation(-Math.PI/2 , y);
				if (!testTube.isValidPosition()) 
					takenPositions.add(new Spherical(-Math.PI/2 , y));
				else
					hasFreeSlots = true;
			}
			y += Math.PI/2;
		}
		return hasFreeSlots;
	}
	
	public boolean hasFreeSlots(Ball ball){
		return mapTakenPositions(ball);
	}
	
	private void createTubeList() {
		Tube tube = null;
		Spherical tData = null;

		double y = 0;
		
		tData = new Spherical(0 , y);
		for (int i = 0 ; i <= 3 ; i ++) {
			tData.setY(y);
			
			if (!isTaken(tData)) {
				tube = factory.createTube(ball.getPos(), tData);
				tube.setStatus(Status.PLACEMENT | Status.TRANSPARENT);

				structure.addTemporaryComponent(tube);
			}	
			
			if (tData.getY() == 0) {
				tData.setZ(Math.PI/2);
				if (!isTaken(tData)) {
					tube = factory.createTube(ball.getPos(), tData);
					tube.setStatus(Status.PLACEMENT | Status.TRANSPARENT);
					
					structure.addTemporaryComponent(tube);
				}	
				tData.setZ(-Math.PI/2);
				if (!isTaken(tData)) {
					tube = factory.createTube(ball.getPos(), tData);
					tube.setStatus(Status.PLACEMENT | Status.TRANSPARENT);
					
					structure.addTemporaryComponent(tube);
				}
				tData.setZ(0);
			}
			y += Math.PI/2;
		}
	}
	
	private boolean isTaken(Spherical tubeData) {
		Iterator<Spherical> takenPosIth = takenPositions.iterator();
		
		Spherical takenData = null;

		while (takenPosIth.hasNext()) {
			takenData = takenPosIth.next();
			if (takenData.getZ() == tubeData.getZ() && takenData.getY() == tubeData.getY()) {
				return true;
			}
		}
		return false;
	}
}
